using System;
using System.Collections.Generic;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using RTMP.SimpleClient.Helpers;

namespace RTMP.SimpleClient.Tests.MockServer
{
    /// <summary>
    /// RTMP 块处理器，用于解析和组装RTMP消息块
    /// </summary>
    public class ChunkProcessor
    {
        private int _chunkSize = 128;
        private readonly Dictionary<int, ChunkStream> _chunkStreams = new();
        private readonly object _lock = new object();

        /// <summary>
        /// 当前块大小
        /// </summary>
        public int ChunkSize
        {
            get { lock (_lock) return _chunkSize; }
            private set { lock (_lock) _chunkSize = value; }
        }

        /// <summary>
        /// 处理接收到的数据并尝试解析完整消息
        /// </summary>
        /// <param name="data">接收到的字节数据</param>
        /// <param name="offset">数据偏移量</param>
        /// <param name="length">数据长度</param>
        /// <returns>解析出的完整消息列表</returns>
        public List<RTMPMessage> ProcessData(byte[] data, int offset, int length)
        {
            var messages = new List<RTMPMessage>();
            int position = offset;
            int endPosition = offset + length;

            while (position < endPosition)
            {
                try
                {
                    var (message, bytesConsumed) = ProcessSingleChunk(data, position, endPosition - position);
                    position += bytesConsumed;

                    if (message != null)
                    {
                        messages.Add(message);
                        
                        // 处理特殊消息类型
                        HandleSpecialMessage(message);
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"[ChunkProcessor] 解析chunk失败: {ex.Message}");
                    // 跳过当前字节，继续处理
                    position++;
                }
            }

            return messages;
        }

        /// <summary>
        /// 处理单个chunk并返回完整消息（如果有）
        /// </summary>
        /// <param name="data">数据缓冲区</param>
        /// <param name="offset">起始位置</param>
        /// <param name="availableBytes">可用字节数</param>
        /// <returns>解析的消息和消耗的字节数</returns>
        private (RTMPMessage? message, int bytesConsumed) ProcessSingleChunk(byte[] data, int offset, int availableBytes)
        {
            if (availableBytes < 1)
                return (null, 0);

            // 解析基本头部
            var (chunkStreamId, chunkType, basicHeaderSize) = ParseBasicHeader(data, offset, availableBytes);
            if (basicHeaderSize == 0)
                return (null, 0); // 需要更多数据

            int position = offset + basicHeaderSize;
            int remaining = availableBytes - basicHeaderSize;

            // 获取或创建chunk stream
            var chunkStream = GetOrCreateChunkStream(chunkStreamId);

            // 解析消息头部
            var (messageHeader, messageHeaderSize) = ParseMessageHeader(data, position, remaining, chunkType, chunkStream);
            if (messageHeaderSize == 0)
                return (null, 0); // 需要更多数据

            position += messageHeaderSize;
            remaining -= messageHeaderSize;

            // 更新chunk stream信息
            UpdateChunkStreamInfo(chunkStream, messageHeader, chunkType);

            // 确定这个chunk的数据大小
            int chunkDataSize = GetChunkDataSize(chunkStream);
            
            if (remaining < chunkDataSize)
                return (null, 0); // 需要更多数据

            // 读取chunk数据
            var chunkData = new byte[chunkDataSize];
            Array.Copy(data, position, chunkData, 0, chunkDataSize);

            // 将chunk数据添加到消息缓冲区
            chunkStream.AppendData(chunkData);

            position += chunkDataSize;
            int totalBytesConsumed = position - offset;

            // 检查消息是否完整
            if (chunkStream.IsMessageComplete())
            {
                var completeMessage = chunkStream.BuildCompleteMessage();
                chunkStream.Reset();
                return (completeMessage, totalBytesConsumed);
            }

            return (null, totalBytesConsumed);
        }

        /// <summary>
        /// 解析基本头部
        /// </summary>
        private (int chunkStreamId, int chunkType, int headerSize) ParseBasicHeader(byte[] data, int offset, int availableBytes)
        {
            if (availableBytes < 1)
                return (0, 0, 0);

            byte firstByte = data[offset];
            int chunkType = (firstByte & 0xC0) >> 6;
            int chunkStreamId = firstByte & 0x3F;

            if (chunkStreamId == 0)
            {
                // 2字节基本头部
                if (availableBytes < 2)
                    return (0, 0, 0);
                chunkStreamId = data[offset + 1] + 64;
                return (chunkStreamId, chunkType, 2);
            }
            else if (chunkStreamId == 1)
            {
                // 3字节基本头部
                if (availableBytes < 3)
                    return (0, 0, 0);
                chunkStreamId = (data[offset + 2] << 8) + data[offset + 1] + 64;
                return (chunkStreamId, chunkType, 3);
            }
            else
            {
                // 1字节基本头部
                return (chunkStreamId, chunkType, 1);
            }
        }

        /// <summary>
        /// 解析消息头部
        /// </summary>
        private (MessageHeader? header, int headerSize) ParseMessageHeader(byte[] data, int offset, int availableBytes, int chunkType, ChunkStream chunkStream)
        {
            var header = new MessageHeader();
            int headerSize = GetMessageHeaderSize(chunkType);

            if (availableBytes < headerSize)
                return (null, 0);

            switch (chunkType)
            {
                case 0: // 完整头部 (11字节)
                    if (availableBytes < 11)
                        return (null, 0);
                    
                    header.Timestamp = ReadUInt24BigEndian(data, offset);
                    header.MessageLength = ReadUInt24BigEndian(data, offset + 3);
                    header.MessageTypeId = data[offset + 6];
                    header.MessageStreamId = ReadUInt32LittleEndian(data, offset + 7);
                    break;

                case 1: // 可变大小头部 (7字节)
                    if (availableBytes < 7)
                        return (null, 0);
                    
                    header.Timestamp = ReadUInt24BigEndian(data, offset);
                    header.MessageLength = ReadUInt24BigEndian(data, offset + 3);
                    header.MessageTypeId = data[offset + 6];
                    header.MessageStreamId = chunkStream.MessageStreamId;
                    break;

                case 2: // 时间戳头部 (3字节)
                    if (availableBytes < 3)
                        return (null, 0);
                    
                    header.Timestamp = ReadUInt24BigEndian(data, offset);
                    header.MessageLength = chunkStream.MessageLength;
                    header.MessageTypeId = chunkStream.MessageTypeId;
                    header.MessageStreamId = chunkStream.MessageStreamId;
                    break;

                case 3: // 无头部
                    header.Timestamp = chunkStream.Timestamp;
                    header.MessageLength = chunkStream.MessageLength;
                    header.MessageTypeId = chunkStream.MessageTypeId;
                    header.MessageStreamId = chunkStream.MessageStreamId;
                    break;
            }

            return (header, headerSize);
        }

        /// <summary>
        /// 处理特殊消息类型
        /// </summary>
        private void HandleSpecialMessage(RTMPMessage message)
        {
            switch (message.MessageTypeId)
            {
                case 1: // Set Chunk Size
                    if (message.Data.Length >= 4)
                    {
                        uint newChunkSize = ReadUInt32BigEndian(message.Data, 0);
                        ChunkSize = (int)newChunkSize;
                        Console.WriteLine($"[ChunkProcessor] Chunk size 设置为: {ChunkSize}");
                    }
                    break;
                    
                case 20: // AMF0 Command
                    Console.WriteLine($"[ChunkProcessor] 收到AMF0命令消息");
                    break;
            }
        }

        /// <summary>
        /// 获取或创建chunk stream
        /// </summary>
        private ChunkStream GetOrCreateChunkStream(int chunkStreamId)
        {
            lock (_lock)
            {
                if (!_chunkStreams.TryGetValue(chunkStreamId, out var chunkStream))
                {
                    chunkStream = new ChunkStream(chunkStreamId);
                    _chunkStreams[chunkStreamId] = chunkStream;
                }
                return chunkStream;
            }
        }

        /// <summary>
        /// 更新chunk stream信息
        /// </summary>
        private void UpdateChunkStreamInfo(ChunkStream chunkStream, MessageHeader? header, int chunkType)
        {
            if (header == null) return;

            if (chunkType <= 2)
            {
                chunkStream.Timestamp = header.Timestamp;
            }
            if (chunkType <= 1)
            {
                chunkStream.MessageLength = header.MessageLength;
                chunkStream.MessageTypeId = header.MessageTypeId;
            }
            if (chunkType == 0)
            {
                chunkStream.MessageStreamId = header.MessageStreamId;
            }
        }

        /// <summary>
        /// 获取chunk数据大小
        /// </summary>
        private int GetChunkDataSize(ChunkStream chunkStream)
        {
            int remainingBytes = (int)(chunkStream.MessageLength - chunkStream.ReceivedBytes);
            return Math.Min(ChunkSize, remainingBytes);
        }

        /// <summary>
        /// 获取消息头部大小
        /// </summary>
        private int GetMessageHeaderSize(int chunkType)
        {
            return chunkType switch
            {
                0 => 11,
                1 => 7,
                2 => 3,
                3 => 0,
                _ => 0
            };
        }

        // 辅助方法：读取大端序整数
        private uint ReadUInt24BigEndian(byte[] data, int offset)
        {
            return (uint)((data[offset] << 16) | (data[offset + 1] << 8) | data[offset + 2]);
        }

        private uint ReadUInt32BigEndian(byte[] data, int offset)
        {
            return (uint)((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]);
        }

        private uint ReadUInt32LittleEndian(byte[] data, int offset)
        {
            return (uint)(data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24));
        }
    }

    /// <summary>
    /// 消息头部信息
    /// </summary>
    public class MessageHeader
    {
        public uint Timestamp { get; set; }
        public uint MessageLength { get; set; }
        public byte MessageTypeId { get; set; }
        public uint MessageStreamId { get; set; }
    }

    /// <summary>
    /// Chunk Stream 状态
    /// </summary>
    public class ChunkStream
    {
        public int ChunkStreamId { get; }
        public uint Timestamp { get; set; }
        public uint MessageLength { get; set; }
        public byte MessageTypeId { get; set; }
        public uint MessageStreamId { get; set; }
        public uint ReceivedBytes => (uint)_buffer.Length;

        private readonly MemoryStream _buffer = new();

        public ChunkStream(int chunkStreamId)
        {
            ChunkStreamId = chunkStreamId;
        }

        public void AppendData(byte[] data)
        {
            _buffer.Write(data, 0, data.Length);
        }

        public bool IsMessageComplete()
        {
            return ReceivedBytes >= MessageLength;
        }

        public RTMPMessage BuildCompleteMessage()
        {
            return new RTMPMessage
            {
                Timestamp = Timestamp,
                MessageLength = MessageLength,
                MessageTypeId = MessageTypeId,
                MessageStreamId = MessageStreamId,
                Data = _buffer.ToArray()
            };
        }

        public void Reset()
        {
            _buffer.SetLength(0);
        }
    }

    /// <summary>
    /// 完整的RTMP消息
    /// </summary>
    public class RTMPMessage
    {
        public uint Timestamp { get; set; }
        public uint MessageLength { get; set; }
        public byte MessageTypeId { get; set; }
        public uint MessageStreamId { get; set; }
        public byte[] Data { get; set; } = Array.Empty<byte>();
    }
}